package base;

import interfaces.IClosedList;
import interfaces.IOpenList;

import java.util.ArrayList;
import java.util.Comparator;

import datastructures.*;


public class GenericSearch implements IOpenList, IClosedList {
	
	protected int searchedNodeCount = 0;
	
	Comparator<MyNode> comp = null;
		
	protected OpenList openlist;
	protected ClosedList closedList;
	
	protected MyNode currentNode;
	protected Object target;
	
	public GenericSearch(Comparator<MyNode> comp) {
		this.openlist = new OpenList(comp);
		this.closedList = new ClosedList();
		this.searchedNodeCount = 0;
		
	}
	
	public MyNode searchValue(MyNode rootNode, int value) {
		this.openlist.add(rootNode);
		return this.search(value);
		
	}
	
	public MyNode searchName(MyNode rootNode, String name){
		this.openlist.add(rootNode);
		return this.search(name);
		
	}

	//generic search algorithm
	public MyNode search(int value) {
		
		//iterative generic search algo style
		while (!this.openlist.isEmpty()) {
			this.searchedNodeCount ++;
			
			this.currentNode = this.investigate(); // currentNode = First in OpenList
			System.out.println("Knoten untersucht -> " + currentNode.getCost());
			this.closedList.add(this.currentNode); //untersuchten knoten in dei closelist packen
			
			if (this.currentNode.getCost() == value) {
				System.out.println("Wert gefunden!");
				return this.currentNode;
			} else {
				ArrayList<MyNode> childs = new ArrayList<MyNode>();
				
				for (MyNode child : this.currentNode.getChilds()) {
					if (!this.closedList.contains(child)) {
						childs.add(child);
					}
				}
				
				this.insert(childs);
				
			}
		}
		System.out.println("Wert nicht gefunden!");
		return null;
	}
	
	// generic search for string
	public MyNode search(String string) {
		this.target = string;		
		
		//iterative generic search algo style
		while (!this.openlist.isEmpty()) {
			this.searchedNodeCount ++;
			
			this.currentNode = this.investigate(); // this.currentNode = First in OpenList
			System.out.println("Knoten untersucht -> " + this.currentNode.getName());
			this.closedList.add(this.currentNode); //untersuchten knoten in dei closelist packen
			
			// hier unterschied zu Seach value: vergleicht strings
			if (this.currentNode.getName().equalsIgnoreCase(string)) {
				System.out.println("Wert gefunden!");
				return this.currentNode;
				
			} else {
				ArrayList<MyNode> childs = new ArrayList<MyNode>();
				
				for (MyNode child : this.currentNode.getChilds()) {
					if (!this.closedList.contains(child) && !this.openlist.contains(child)) {
						childs.add(child);
					}
				}
				
				this.insert(childs);
				
			}
		}
		System.out.println("Wert nicht gefunden!");
		return null;
	}

	@Override
	public void insert(ArrayList<MyNode> node) {
		
	}

	@Override
	public MyNode investigate() {
		System.out.println("investigate with null -> dont override");
		return null;
	}

	public int getSearchedNodeCount() {
		return searchedNodeCount;
	}

	public void setSearchedNodeCount(int searchedNodeCount) {
		this.searchedNodeCount = searchedNodeCount;
	}

	@Override
	public void add(MyNode node) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean contains(MyNode node) {
		// TODO Auto-generated method stub
		return false;
	}

	public MyNode getCurrentNode() {
		return currentNode;
	}

	public void setCurrentNode(MyNode currentNode) {
		this.currentNode = currentNode;
	}

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
	
}
